home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / progutil / iostream.zoo / src / iostream.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-22  |  12.7 KB  |  586 lines

  1. //    This is part of the iostream library, providing input/output for C++.
  2. //    Copyright (C) 1991 Per Bothner.
  3. //
  4. //    This library is free software; you can redistribute it and/or
  5. //    modify it under the terms of the GNU Library General Public
  6. //    License as published by the Free Software Foundation; either
  7. //    version 2 of the License, or (at your option) any later version.
  8. //
  9. //    This library is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. //    Library General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU Library General Public
  15. //    License along with this library; if not, write to the Free
  16. //    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #pragma implementation
  19. #include "ioprivat.h"
  20. #include <iostream.h>
  21. #include <ctype.h>
  22. #include "floatio.h"
  23.  
  24. #define    BUF        (MAXEXP+MAXFRACT+1)    /* + decimal point */
  25.  
  26. //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
  27.  
  28. extern streambuf not_open_filebuf;
  29.  
  30. int istream::good() // For now
  31. {
  32.     return _strbuf != ¬_open_filebuf;
  33. }
  34.  
  35. #ifdef OLD_STDIO
  36. int ostream::good() // For now
  37. {
  38.     return _strbuf != ¬_open_filebuf;
  39. }
  40. #endif
  41.  
  42. istream::istream() : ios(¬_open_filebuf)
  43. {
  44.     _flags |= ios::dont_close;
  45.     _gcount = 0;
  46.     _tie = NULL;
  47. }
  48.  
  49. istream::istream(streambuf *sb, ostream* tied) : ios(sb)
  50. {
  51. #if 0
  52.     _flags |= ios::dont_close;
  53. #else
  54.     _flags &=  ~((unsigned long)(ios::dont_close));
  55. #endif
  56.     _gcount = 0;
  57.     _tie = tied;
  58. }
  59.  
  60. void istream::close()
  61. {
  62.     if (!(_flags & (unsigned int)ios::dont_close))
  63.     delete _strbuf;
  64.     _flags |= ios::dont_close;
  65.     _strbuf = ¬_open_filebuf;
  66. }
  67.  
  68. istream::~istream()
  69. {
  70.     close();
  71. }
  72.  
  73. int skip_ws(streambuf* sb)
  74. {
  75.     int ch;
  76.     for (;;) {
  77.     ch = sb->sbumpc();
  78.     if (ch == EOF || !isspace(ch))
  79.         return ch;
  80.     }
  81. }
  82.  
  83. istream& istream::get(char& c)
  84. {
  85.     if (ipfx1()) {
  86.     int ch = _strbuf->sbumpc();
  87.     if (ch == EOF) clear(rdstate()|ios::failbit);
  88.     else c = (char)ch;
  89.     }
  90.     return *this;
  91. }
  92.  
  93. istream& istream::get(unsigned char& c)
  94. {
  95.     if (ipfx1()) {
  96.     int ch = _strbuf->sbumpc();
  97.     if (ch == EOF) clear(rdstate()|ios::failbit);
  98.     else c = (unsigned char)ch;
  99.     }
  100.     return *this;
  101. }
  102.  
  103. istream& istream::operator>>(char& c)
  104. {
  105.     if (ipfx0()) {
  106.     int ch = _strbuf->sbumpc();
  107.     if (ch == EOF)
  108.         clear(rdstate()|(ios::eofbit|ios::failbit));
  109.     else
  110.         c = (char)ch;
  111.     }
  112.     return *this;
  113. }
  114.  
  115. istream& istream::operator>>(unsigned char& c)
  116. {
  117.     if (ipfx0()) {
  118.     int ch = _strbuf->sbumpc();
  119.     if (ch == EOF)
  120.         clear(rdstate()|(ios::eofbit|ios::failbit));
  121.     else
  122.         c = (unsigned char)ch;
  123.     }
  124.     return *this;
  125. }
  126.  
  127. istream& istream::operator>>(char* ptr)
  128. {
  129.     if (ipfx0()) {
  130.     register streambuf* sb = _strbuf;
  131.     int ch = sb->sbumpc();
  132.     if (ch == EOF)
  133.         clear(rdstate()|(ios::eofbit|ios::failbit));
  134.     else {
  135.         int w = width(0); // FIXME: Not used!
  136.         *ptr++ = ch;
  137.         for (;;) {
  138.         ch = sb->sbumpc();
  139.         if (ch == EOF)
  140.             break;
  141.         else if (isspace(ch)) {
  142.             sb->sputbackc(ch);
  143.             break;
  144.         }
  145.         }
  146.         *ptr++ = 0;
  147.     }
  148.     }
  149.     return *this;
  150. }
  151.  
  152. static int read_int(istream& stream, unsigned long& val, int& neg)
  153. {
  154.     if (!stream.ipfx0())
  155.     return 0;
  156.     register streambuf* sb = stream.rdbuf();
  157.     int base = 10;
  158.     int ndigits = 0;
  159.     register int ch = skip_ws(sb);;
  160.     if (ch == EOF)
  161.     goto fail;
  162.     neg = 0;
  163.     if (ch == '+') {
  164.     ch = skip_ws(sb);
  165.     }
  166.     else if (ch == '-') {
  167.     neg = 1;
  168.     ch = skip_ws(sb);
  169.     }
  170.     if (ch == EOF) goto fail;
  171.     if (stream.flags() & (ios::hex|ios::dec|ios::oct)) {
  172.     if (ch == '0') {
  173.         ch = sb->sbumpc();
  174.         if (ch == EOF) {
  175.         val = 0;
  176.         return 1;
  177.         }
  178.         if (ch == 'x' || ch == 'X') {
  179.         base = 16;
  180.         ch = sb->sbumpc();
  181.         if (ch == EOF) goto fail;
  182.         }
  183.         else
  184.         base = 8;
  185.     }
  186.     }
  187.     else if (stream.flags() & ios::hex)
  188.     base = 16;
  189.     else if (stream.flags() & ios::oct)
  190.     base = 8;
  191.     val = 0;
  192.     for (;;) {
  193.     if (ch == EOF)
  194.         break;
  195.     int digit;
  196.     if (ch >= '0' && ch <= '9')
  197.         digit = ch - '0';
  198.     else if (ch >= 'A' && ch <= 'F')
  199.         digit = ch - 'A' + 10;
  200.     else if (ch >= 'a' && ch <= 'f')
  201.         digit = ch - 'a' + 10;
  202.     else
  203.         digit = 999;
  204.     if (digit >= base)
  205.         if (ndigits == 0) goto fail;
  206.         else {
  207.         sb->sputbackc(ch);
  208.         return 1;
  209.         }
  210.     ndigits++;
  211.     val = 10 * val + digit;
  212.     ch = sb->sbumpc();
  213.     }
  214.     return 1;
  215.   fail:
  216.     stream.clear(stream.rdstate()|ios::failbit);
  217.     return 0;
  218. }
  219.  
  220. #define READ_INT(TYPE) \
  221. istream& istream::operator>>(TYPE& i)\
  222. {\
  223.     unsigned long val; int neg;\
  224.     if (read_int(*this, val, neg)) {\
  225.     if (neg) val = -val;\
  226.     i = (TYPE)val;\
  227.     }\
  228.     return *this;\
  229. }
  230.  
  231. READ_INT(short)
  232. READ_INT(unsigned short)
  233. READ_INT(int)
  234. READ_INT(unsigned int)
  235. READ_INT(long)
  236. READ_INT(unsigned long)
  237.  
  238. istream& istream::operator>>(double& x)
  239. {
  240.     if (ipfx0()) {
  241.     double* ptr = &x;
  242.     __vsbscanf(rdbuf(), "%lg", (va_list)&ptr);
  243.     }
  244.     return *this;
  245. }
  246. istream& istream::operator>>(float& x)
  247. {
  248.     if (ipfx0()) {
  249.     float* ptr = &x;
  250.     __vsbscanf(rdbuf(), "%g", (va_list)&ptr);
  251.     }
  252.     return *this;
  253. }
  254.  
  255. inline ostream& ostream::operator<<(char c)
  256. {
  257.     if (opfx()) {
  258.     int w = width(0);
  259.     char fill_char = fill();
  260.     register int padding = w > 0 ? w - 1 : 0;
  261.     if (!(flags() & ios::left)) // Default adjustment.
  262.         while (--padding >= 0) _strbuf->sputc(fill_char);
  263.     _strbuf->sputc(c);
  264.     if (flags() & ios::left) // Left adjustment.
  265.         while (--padding >= 0) _strbuf->sputc(fill_char);
  266.     osfx();
  267.     }
  268.     return *this;
  269. }
  270.  
  271. void write_int(ostream& stream, unsigned long val, int neg)
  272. {
  273.     char buf[10 + sizeof(unsigned long) * 3];
  274.     char *show_base = "";
  275.     int show_base_len = 0;
  276.     if ((stream.flags() & (ios::oct|ios::hex)) == 0) // Decimal
  277.     sprintf(buf, "%lu", val);
  278.     else if (stream.flags() & ios::oct) { // Oct
  279.     sprintf(buf, "%lo", val);
  280.     if (stream.flags() && ios::showbase)
  281.         show_base = "0"; show_base_len = 1;
  282.     }
  283.     else if (stream.flags() & ios::uppercase) {// Hex
  284.     sprintf(buf, "%lX", val);
  285.     if (stream.flags() && ios::showbase)
  286.         show_base = "0X"; show_base_len = 2;
  287.     }
  288.     else { // Hex
  289.     sprintf(buf, "%lx", val);
  290.     if (stream.flags() && ios::showbase)
  291.         show_base = "0x"; show_base_len = 2;
  292.     }
  293.     int buf_len = strlen(buf);
  294.     int w = stream.width(0);
  295.     int show_pos = 0;
  296.     int i;
  297.  
  298.     // Calculate padding.
  299.     int len = buf_len;
  300.     if (neg) len++;
  301.     else if (val != 0 && (stream.flags() & ios::showpos)) len++, show_pos=1;
  302.     len += show_base_len;
  303.     int padding = len > w ? 0 : w - len;
  304.  
  305.     // Do actual output.
  306.     register streambuf* sbuf = stream.rdbuf();
  307.     unsigned long pad_kind =
  308.     stream.flags() & (ios::left|ios::right|ios::internal);
  309.     char fill_char = stream.fill();
  310.     if (pad_kind != (unsigned long)ios::left // Default (right) adjustment.
  311.     && pad_kind != (unsigned long)ios::internal)
  312.     for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  313.     if (neg) sbuf->sputc('-');
  314.     else if (show_pos) sbuf->sputc('+');
  315.     if (show_base_len)
  316.     sbuf->sputn(show_base, show_base_len);
  317.     if (pad_kind == (unsigned long)ios::internal)
  318.     for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  319.     sbuf->sputn(buf, buf_len);
  320.     if (pad_kind == (unsigned long)ios::left) // Left adjustment.
  321.     for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  322.     stream.osfx();
  323. }
  324.  
  325. ostream& ostream::operator<<(int n)
  326. {
  327.     if (opfx()) {
  328.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  329.         write_int(*this, -n, 1);
  330.     else
  331.         write_int(*this, n, 0);
  332.     }
  333.     return *this;
  334. }
  335.  
  336. ostream& ostream::operator<<(long n)
  337. {
  338.     if (opfx()) {
  339.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  340.         write_int(*this, -n, 1);
  341.     else
  342.         write_int(*this, n, 0);
  343.     }
  344.     return *this;
  345. }
  346.  
  347. ostream& ostream::operator<<(unsigned int n)
  348. {
  349.     if (opfx())
  350.     write_int(*this, n, 0);
  351.     return *this;
  352. }
  353.  
  354. ostream& ostream::operator<<(unsigned long n)
  355. {
  356.     if (opfx())
  357.     write_int(*this, n, 0);
  358.     return *this;
  359. }
  360.  
  361. ostream& ostream::operator<<(float n)
  362. {
  363.     return *this << (double)n;
  364. }
  365.  
  366. ostream& ostream::operator<<(double n)
  367. {
  368.     if (opfx()) {
  369.     // Uses __cvt_double (renamed from static cvt), in Chris Torek's
  370.     // stdio implementation.  The setup code uses the same logic
  371.     // as in __vsbprintf.C (also based on Torek's code).
  372.     char negative;
  373.     char buf[BUF];
  374.     int format_char;
  375.     int sign = '\0';
  376. #if 0
  377.     if (flags() ios::showpos) sign = '+';
  378. #endif
  379.     if (flags() & ios::fixed)
  380.         format_char = 'f';
  381.     else if (flags() & ios::scientific)
  382.         format_char = flags() & ios::uppercase ? 'E' : 'e';
  383.     else
  384.         format_char = flags() & ios::uppercase ? 'G' : 'g';
  385.  
  386.     int fpprec = 0; // 'Extra' (suppressed) floating precision.
  387.     int prec = precision();
  388.     if (prec < 0) prec = 6; // default.
  389.     else if (prec > MAXFRACT) {
  390.         if (flags() & (ios::fixed|ios::scientific) & ios::showpos)
  391.         fpprec = prec - MAXFRACT;
  392.         prec = MAXFRACT;
  393.     }
  394.  
  395.     // Do actual conversion.
  396.     char *cp = buf;
  397.     *cp = 0;
  398.     int size = __cvt_double(n, precision(),
  399.                 flags() & ios::showpoint ? 0x80 : 0,
  400.                 &negative,
  401.                 format_char, cp, buf + sizeof(buf));
  402.     if (negative) sign = '-';
  403.     if (*cp == 0)
  404.         cp++;
  405.  
  406.     // Calculate padding.
  407.     int fieldsize = size + fpprec;
  408.     if (sign) fieldsize++;
  409.     int padding = 0;
  410.     int w = width(0);
  411.     if (fieldsize < w)
  412.         padding = w - fieldsize;
  413.  
  414.     // Do actual output.
  415.     register streambuf* sbuf = rdbuf();
  416.     register i;
  417.     char fill_char = fill();
  418.     unsigned long pad_kind =
  419.         flags() & (ios::left|ios::right|ios::internal);
  420.     if (pad_kind != (unsigned long)ios::left // Default (right) adjust.
  421.         && pad_kind != (unsigned long)ios::internal)
  422.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  423.     if (sign)
  424.         sbuf->sputc(sign);
  425.     if (pad_kind == (unsigned long)ios::internal)
  426.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  427.     
  428.     // Emit the actual concented field, followed by extra zeros.
  429.     sbuf->sputn(cp, size);
  430.     for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
  431.  
  432.     if (pad_kind == (unsigned long)ios::left) // Left adjustment
  433.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  434.     osfx();
  435.     }
  436.     return *this;
  437. }
  438.  
  439. inline ostream& ostream::operator<<(const char *s)
  440. {
  441.     if (opfx()) {
  442.     int len = strlen(s);
  443.     int w = width(0);
  444.     char fill_char = fill();
  445.     register int padding = w > len ? w - len : 0;
  446.     if (!(flags() & ios::left)) // Default adjustment.
  447.         while (--padding >= 0) _strbuf->sputc(fill_char);
  448.     _strbuf->sputn(s, len);
  449.     if (flags() & ios::left) // Left adjustment.
  450.         while (--padding >= 0) _strbuf->sputc(fill_char);
  451.     osfx();
  452.     }
  453.     return *this;
  454. }
  455.  
  456. ostream& ostream::operator<<(void *p)
  457. {
  458.     if (opfx()) {
  459.     __sbprintf(_strbuf, "0x%x", p);
  460.     osfx();
  461.     }
  462.     return *this;
  463. }
  464.  
  465. ostream& ostream::operator<<(register streambuf* sbuf)
  466. {
  467.     if (opfx()) {
  468.     register streambuf* outbuf = rdbuf();
  469.     // NOTE: Should optimize!
  470.     for (;;) {
  471.         register int ch = sbuf->sbumpc();
  472.         if (ch == EOF) break;
  473.         outbuf->sputc(ch);
  474.     }
  475.     osfx();
  476.     }
  477.     return *this;
  478. }
  479.  
  480. ostream::ostream() : ios(¬_open_filebuf)
  481. {
  482.     _flags |= ios::dont_close;
  483.     _tie = NULL;
  484. }
  485.  
  486. ostream::ostream(streambuf* sb, ostream* tied) : ios(sb)
  487. {
  488. #if 0
  489.     _flags |= ios::dont_close;
  490. #else
  491.     _flags &= ~((unsigned long)(ios::dont_close));
  492. #endif
  493.     _tie = tied;
  494. }
  495.  
  496. void ostream::close()
  497. {
  498.     if (!(_flags & (unsigned int)ios::dont_close))
  499.     delete _strbuf;
  500.     _flags |= ios::dont_close;
  501.     _strbuf = ¬_open_filebuf;
  502. }
  503.  
  504. ostream::~ostream()
  505. {
  506.     close();
  507. }
  508.  
  509. ostream& ostream::form(const char *format ...)
  510. {
  511.     va_list ap;
  512.     va_start(ap, format);
  513.     __vsbprintf(_strbuf, format, ap);
  514.     va_end(ap);
  515.     return *this;
  516. }
  517.  
  518. inline ostream& ostream::flush()
  519. {
  520.     if (_strbuf->sync())
  521.     clear(rdstate() | ios::badbit);
  522.     return *this;
  523. }
  524.  
  525. #ifndef IMPLEMENT_STDIO
  526. extern streambuf CIN_STREAMBUF[1];
  527. extern streambuf COUT_STREAMBUF[1];
  528. extern streambuf CERR_STREAMBUF[1];
  529. #define CLOG_STREAMBUF CERR_STREAMBUF
  530. #endif
  531.  
  532. istream cin((streambuf*)CIN_STREAMBUF, &cout);
  533. ostream cout((streambuf*)COUT_STREAMBUF);
  534. ostream cerr((streambuf*)CERR_STREAMBUF, &cout);
  535. ostream clog((streambuf*)CLOG_STREAMBUF, &cout);
  536.  
  537. ostream& flush(ostream& outs)
  538. {
  539.     outs.rdbuf()->overflow(EOF);
  540.     return outs;
  541. }
  542.  
  543. istream& ws(istream& ins)
  544. {
  545. #if 1
  546.     for (;;) {
  547.     int ch = ins._strbuf->sbumpc();
  548.     if (ch == EOF) break;
  549.     if (isspace(ch)) continue;
  550.     ins._strbuf->sputbackc(ch);
  551.     break;
  552.     }
  553. #else
  554.     int ch = ins._strbuf->sgetc();
  555.     while (ch != EOF && isspace(ch))
  556.     ch = ins._strbuf->snextc();
  557. #endif
  558.     return ins;
  559. }
  560.  
  561. ostream& ends(ostream& outs)
  562. {
  563.     outs.put(0);
  564.     return outs;
  565. }
  566.  
  567. ostream& endl(ostream& outs)
  568. {
  569.     return flush(outs.put('\n'));
  570. }
  571.  
  572. void ostream::do_osfx()
  573. {
  574.     if (flags() & ios::unitbuf)
  575.     flush();
  576.     if (flags() & ios::stdio) {
  577.     fflush(stdout);
  578.     fflush(stderr);
  579.     }
  580. }
  581.  
  582. static const unsigned long ios::basefield = ios::hex|ios::oct|ios::dec;
  583. static const unsigned long ios::floatfield = ios::scientific|ios::fixed;
  584. static const unsigned long ios::adjustfield =
  585.     ios::left|ios::right|ios::internal;
  586.